##    Copyright 2007 David Blewett
##
##   Licensed under the Apache License, Version 2.0 (the "License");
##   you may not use this file except in compliance with the License.
##   You may obtain a copy of the License at
##
##       http://www.apache.org/licenses/LICENSE-2.0
##
##   Unless required by applicable law or agreed to in writing, software
##   distributed under the License is distributed on an "AS IS" BASIS,
##   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
##   See the License for the specific language governing permissions and
##   limitations under the License.
## Author: David Blewett
## Contact: david@dawninglight.net
from utils import parse_fetch_response, parse_nested_parens

#Map response keywords to Mailbox arguments
class IMAPCommand(object):
    def __init__(self, method, responses=None, to_python=parse_nested_parens):
        self.method = method
        if responses is None:
            self.responses = {}
            self.to_python = to_python
        else:
            self.responses = dict([(k, responses[k][0]) for k in responses])
            self.to_python = dict([(k, responses[k][1]) for k in responses])

LOGIN = IMAPCommand(method='login')

SELECT = IMAPCommand(method='select', 
                     responses={ 
                                'FLAGS': ('flags', parse_nested_parens),
                                'EXISTS': ('exists', int),
                                'RECENT': ('recent', int),
                                'UNSEEN': ('unseen', int),
                                'PERMANENTFLAGS': ('permanent_flags', parse_nested_parens),
                                'UIDNEXT': ('uid_next', int),
                                'UIDVALIDITY': ('uid_validity', int),
                                })
SEARCH = IMAPCommand(method='search')
NOOP = IMAPCommand(method='noop', responses={'RECENT': ('recent',  int)})
CLOSE = IMAPCommand(method='close')

FETCH_ITEMS = [
    'BODY', 
    'BODY.PEEK', 
    'BODYPORTION', 
    'BODYPORTION.PEEK', 
    'BODYSTRUCTURE', 
    'ENVELOPE', 
    'FLAGS', 
    'INTERNALDATE', 
    'RFC822', 
    'RFC822.HEADER', 
    'RFC822.SIZE', 
    'RFC822.TEXT', 
    'UID', 
]

FETCH_MACROS = {
    'ALL': ('FLAGS', 'INTERNALDATE', 'RFC822.SIZE', 'ENVELOPE'), 
    'FAST': ('FLAGS', 'INTERNALDATE', 'RFC822.SIZE'),
    'FULL': ('FLAGS', 'INTERNALDATE', 'RFC822.SIZE', 'ENVELOPE', 'BODY')
}

class BodyItem(object):
    def __init__(self, peek=False, section=None, partial=None):
        self.peek = peek
        self.section = section
        self.partial = partial
        
    def __unicode__(self):
        cmd = 'BODY'
        if self.peek:
            cmd = '%s.PEEK' % cmd 
        if self.section:
            cmd = '%s[%s' % (cmd, '[', self.section)
            if self.partial:
                cmd = '%s (%s)' % (cmd,  ' '.join(self.partial), ')')
            cmd = '%s]' % cmd
        return cmd

class IMAPFetchCommand(IMAPCommand):
    """
    Class to create an IMAP fetch command string. example:
    
    i = BodyItem('HEADER.FIELDS', ('subject', 'from', 'date'))
    fetch = FetchCommand(i, 'FLAGS', 'INTERNALDATE')
    ?fetch
    '(BODY[HEADER.FIELDS (subject from date)] FLAGS INTERNALDATE)'
    """
    def __init__(self, *items):
        super(IMAPFetchCommand, self).__init__('fetch', to_python=parse_fetch_response)
        self.items = items

    def __unicode__(self):
        items = ''
        for i in self.items:
            if i in IMAP_MACROS:
                items += ' '.join(IMAP_MACROS[i])
            else:
                items += ' ' + str(i)
        items = items.strip()
        cmd = '(%s)' % items

        return cmd
